import 'dart:async';
import 'dart:convert';
import 'package:web_socket_channel/web_socket_channel.dart';


class WebsocketManager{

  late WebSocketChannel socketChannel;
  // 连接状态
  bool state = false;
  // 是否为主动断开
  bool isDisconnect = false;
  // 心跳间隔
  int heartTime = 5000;
  // 心跳定时器
  late Timer heartBeat;
  // 连接服务地址
  String serviceUrl = "ws://192.168.100.199:8081/ws/";
  // 重连时间间隔s
  Duration reconnectInterval = const Duration(seconds: 5);

  final String? userId;

  final String? device;

  StreamController<Map<String, dynamic>> messageController = StreamController<Map<String, dynamic>>();

  Stream<Map<String, dynamic>> get messageStream => messageController.stream;

  WebsocketManager({this.userId, this.device});

  WebsocketManager connection(){
    socketChannel = WebSocketChannel.connect(Uri.parse(serviceUrl + userId! + "/" +device!));
    socketChannel.stream.listen((data) => isSuccess(data));
    return WebsocketManager();
  }

  void isSuccess(data){
    dynamic result = jsonDecode(data);
    handlerMessage(result);
    if(result['eventName'] == '__login_success'){
        state = true;
        heart(result['data']['userId']);
    }
  }

  void heart(String userId){
    heartBeat = Timer.periodic(Duration(milliseconds: heartTime), (Timer timer){
        final message = {"eventName": '__heart', 'data': {'userId': userId}};
        state ? sendMessage(message) : '';
    });
  }

  void stopHeart(){
    heartBeat.cancel();
  }

  Future<void> sendMessage(Map<String, dynamic> message) async{
    state ? socketChannel.sink.add(jsonEncode(message)) : error(message);
  }

  void handlerMessage(data) async{
    print(data);
    messageController.add(data);
    // switch(data['eventName']){
    //   case '__task_scheduling': handlerTask(data); break;
    // }
  }

  void handlerTask(message){
    print(message);
  }

  void disconnect(){
    state = false;
    isDisconnect = true;
    stopHeart();
  }

  void error(message){
    if(!isDisconnect){
      reconnect();
      state ? sendMessage(message) : '';
    }
  }

  void reconnect(){
    Timer(reconnectInterval, (){
      state = false;
      socketChannel.sink.close();
      connection();
    });
  }
}